<?php
/*
 Copyright 2006 Iván Montes, Morten Hundevad

 This file is part of FLV tools for PHP (FLV4PHP from now on).

 FLV4PHP is free software; you can redistribute it and/or modify it under the 
 terms of the GNU General var License as published by the Free Software 
 Foundation; either version 2 of the License, or (at your option) any later 
 version.

 FLV4PHP is distributed in the hope that it will be useful, but WITHOUT ANY 
 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 
 A PARTICULAR PURPOSE. See the GNU General var License for more details.

 You should have received a copy of the GNU General var License along with 
 FLV4PHP; if not, write to the Free Software Foundation, Inc., 51 Franklin 
 Street, Fifth Floor, Boston, MA 02110-1301, USA
*/

/**
 * A simple streamer class to work with bit sequences and extract integers
 *
 */
class FLV_Util_BitStreamReader {

	var $data;
	var $bits;
	var $pos;
	var $ofs;

	/**
	 * Class constructor which can initilaze the stream
	 *
	 * @param string $data	An optional binary string
	 */
	function FLV_Util_BitStreamReader( $data = '' )
	{
	    $this->__construct( $data );
	}
	function __construct( $data = '' )
	{
	    $this->setPayload( $data );
	}

	/**
	 * Sets the binary stream to use
	 *
	 * @param string $data	The binary string
	 */
	function setPayload( $data )
	{
		$this->data = $data;
		$this->pos = 0;
		$this->bits = '';
		$this->ofs = 0;
	}
  
	/**
	 * Makes sure we have the requested number of bits in the working buffer
	 * 
	 * @access private
 	 * @param int $cnt	The number of bits needed
	 */
	function fetch( $cnt )
	{
        if ($this->pos < $this->ofs*8 ||
            $this->pos + $cnt > $this->ofs*8 + strlen($this->bits) )
        {       
            $this->bits = '';
            $this->ofs = FLOOR($this->pos/8);
            for ($i = $this->ofs; $i <= $this->ofs + CEIL($cnt/8); $i++ )
            {
                $this->bits .= str_pad( decbin(ord($this->data[$i])), 8, '0', STR_PAD_LEFT );
            }
        }		
	}
	
	/**
	 * Consume an integer from an arbitrary number of bits in the stream
	 * 
	 * @param int $cnt	Length in bits of the integer
	 */
	function getInt( $cnt )
	{
		$this->fetch( $cnt );
		
		$ret = bindec( substr($this->bits, $this->pos-($this->ofs << 3), $cnt) );
		$this->pos += $cnt;
		return $ret;
	}

	/**
	 * Seeks into the bit stream in a similar way to fseek()
	 * 
	 * @param int $cnt	Number of bits to seek
	 * @param int $whence Either SEEK_SET (default), SEEK_CUR or SEEK_END
	 */	
	function seek( $ofs, $whence = SEEK_SET )
	{
		switch ($whence)
		{
			case SEEK_SET:
				$this->pos = $ofs;
			break;
			case SEEK_CUR:
				$this->pos += $ofs;
			break;
			case SEEK_END:
				$this->pos -= strlen($this->data)*8 - $ofs;
			break;
		}
		
		if ($this->pos < 0)
			$this->pos;
		elseif ($this->pos > strlen($this->data)*8)
			$this->pos = $this->data*8;
	}
}

?>